home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1998 September
/
Macformat_MF67_1998-09.iso
/
Shareware Plus
/
Development
/
SpriteWorld 2.1 Extra Demos
/
Platform Scrolling
/
Platform Scrolling.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-28
|
27KB
|
937 lines
///--------------------------------------------------------------------------------------
// Platform Scrolling.c
//
// By Vern Jensen. Created in September, 1997.
///--------------------------------------------------------------------------------------
#include <SWFPSReport.h>
#include <SWIncludes.h>
#include <SWGameUtils.h>
#include <SWApplication.h>
#include "Platform Scrolling.h"
#define kFullScreenWindow true // Toggles between 512x384 and 640x480
#define kWorldRectInset 0 // Make the SpriteWorld smaller?
#define kInterlacedMode false // Turns Interlaced mode on/off
#define kSyncToVBL false // Sync SpriteWorld to VBL?
#define kMaxFPS 30 // Set to 0 for unrestricted speed
#define kWalkIncrease 1
#define kMaxWalkSpeed 10
#define kMaxFallSpeed 20
#define kJumpSpeed 26
#define kMaxSpriteJumpDistance 19 // How many frames the sprite can keep going up
#define kGravitySpeed 2
#define kMovingFloorSpeed 0 // How often the moving floors change frames
#define kMovingFloorForce 2 // How far they move the sprite when the move
#define kChangingFloorSpeed 5 // Frame rate of the changing floor
#define kChangingFloorWait 120 // How long of a delay between on/off
#define kSpikeSpeed 2 // How fast the spikes move
#define kSpikeChangeDelay 150 // How long they wait between moves
#define kExitSignSpeed 8 // Animation speed of exit sign
#define kArrowSpeed 10 // Animation speed of arrow
#define kRunningCorrection 7 // Determines how many pixel a sprite can fall through
// the top of a tile and still be put back on top.
// Useful for running across tiles with holes inbetween.
#define kSpriteMoveDistance 80 // How far the sprite can move from
// the center of the screen, in pixels.
// Try making this value higher!
#define kTileWidth 40
#define kTileHeight 40
#define kStartRow 5 // Starting position of sprite
#define kStartCol 5 // in tile col and row
#define kLeftArrowKey 0x7B
#define kRightArrowKey 0x7C
#define kDownArrowKey 0x7D
#define kUpArrowKey 0x7E
#define kLeftKeyPad 0x56
#define kRightKeyPad 0x58
#define kDownKeyPad 0x54
#define kUpKeyPad 0x5B
#define kEscKey 0x35
enum tileIDs
{
kFirstWallTile = 0,
kLastWallTile = 9,
kFirstSpikeTile,
kLastSpikeTile = kFirstSpikeTile + 15,
kBackgroundTile,
kFirstLeftFloorTile,
kLastLeftFloorTile = kFirstLeftFloorTile + 4,
kFirstRightFloorTile,
kLastRightFloorTile = kFirstRightFloorTile + 4,
kFirstChangingTile,
kLastChangingTile = kFirstChangingTile + 2,
kFirstBackgroundTile,
kLastBackgroundTile = kFirstBackgroundTile + 8,
kFirstExitTile,
kLastExitTile = kFirstExitTile + 2,
kMaxNumTiles
};
/***********/
/* Globals */
/***********/
SpriteWorldPtr gSpriteWorldP;
SpriteLayerPtr gSpriteLayerP;
TileMapStructPtr gTileMapStructP;
TileMapPtr gTileMap;
SpritePtr gSimpleSpriteP;
WindowPtr gWindowP;
short gCurrentLevel = 128;
Rect gScreenMidRect, gSpriteInsetRect;
Boolean gSpriteCanJump, gSpriteIsJumping, gSpriteJumpStage;
Boolean gChangingFloorMode = true;
Boolean gDone = false;
Boolean gEscapeKey = false;
Boolean gSpikesAreUp = true;
Boolean gSpriteHitExit = false, gSpriteWasKilled = false;
struct moveKeys
{
Boolean up;
Boolean right;
Boolean down;
Boolean left;
Boolean jump;
} gKeys;
///--------------------------------------------------------------------------------------
// Main
///--------------------------------------------------------------------------------------
void main( void )
{
Initialize(kNumberOfMoreMastersCalls);
if (SWHasSystem7())
{
AllowKeyUpEvents(); // Part of SWGameUtils.c
SetCursor(*GetCursor(watchCursor));
CreateWindow();
CreateSpriteWorld();
CreateBallSprite();
SWLockSpriteWorld(gSpriteWorldP);
SetCursor(&qd.arrow);
HideCursor();
SetUpAnimation();
RunAnimation();
ShutDown();
RestoreEventMask(); // Call this after AllowKeyUpEvents
}
else
{
CantRunOnThisMachine();
}
}
///--------------------------------------------------------------------------------------
// CreateWindow
///--------------------------------------------------------------------------------------
void CreateWindow( void )
{
Rect windRect;
RgnHandle mBarUpdateRgn;
gWindowP = GetNewCWindow(128, NULL, (WindowPtr)-1L);
if (gWindowP == NULL)
{
CantFindResource();
}
else
{
if (kFullScreenWindow)
{
SizeWindow(gWindowP, SW_MIN(640, qd.screenBits.bounds.right),
SW_MIN(480, qd.screenBits.bounds.bottom), false);
}
else
{
SizeWindow(gWindowP, 512, 384, false);
}
// Center window in screen
windRect = gWindowP->portRect;
CenterRect(&windRect, &qd.screenBits.bounds);
// Make sure window is aligned to long-word boundaries (for 8-bit mode)
windRect.left = windRect.left>>2<<2;
MoveWindow(gWindowP, windRect.left, windRect.top, false);
ShowWindow(gWindowP);
SetPort(gWindowP);
}
mBarUpdateRgn = HideMenuBar(gWindowP);
EraseRgn(mBarUpdateRgn);
DisposeRgn(mBarUpdateRgn);
}
///--------------------------------------------------------------------------------------
// CreateSpriteWorld
///--------------------------------------------------------------------------------------
void CreateSpriteWorld( void )
{
Rect offscreenRect, worldRect;
OSErr err;
err = SWEnterSpriteWorld();
FatalError(err);
worldRect = gWindowP->portRect;
InsetRect(&worldRect, kWorldRectInset, kWorldRectInset);
// Set size of offscreen area
offscreenRect = worldRect;
OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
// Make offscreen area evenly divisible by tile width & height
if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
// Create the scrolling sprite world
err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP,
&worldRect, &offscreenRect, 0);
FatalError(err);
// Create the sprite layer
err = SWCreateSpriteLayer(&gSpriteLayerP);
FatalError(err);
// Add it to the world
SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);
err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
FatalError(err);
err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
FatalError(err);
SWInstallTileMap(gSpriteWorldP, gTileMapStructP);
gTileMap = gTileMapStructP->tileMap;
// Load first set of tiles
err = SWLoadTilesFromPictResource(
gSpriteWorldP,
0, // startTileID
kMaxNumTiles-1, // endTileID
200, // pictResID
0, // maskResID
kNoMask, // maskType
0, // horizBorderWidth
0); // vertBorderHeight
FatalError(err);
}
///--------------------------------------------------------------------------------------
// CreateBallSprite
///--------------------------------------------------------------------------------------
void CreateBallSprite( void )
{
OSErr err;
// Create the ball sprite
err = SWCreateSpriteFromSinglePict(gSpriteWorldP, &gSimpleSpriteP, NULL,
128, 128, 40, 0, kFatMask);
FatalError(err);
// Set up the ball sprite
SWLockSprite(gSimpleSpriteP);
SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
// Inset for left, top, right, and bottom of sprite when checking sprite with tiles
SetRect(&gSpriteInsetRect, 5, 4, 5, 0);
gSpriteCanJump = true;
gSpriteIsJumping = false;
gSpriteJumpStage = 0;
// Set the sprite's drawProc
if (gSpriteWorldP->pixelDepth == 8) // If in 256 colors
{
if (kInterlacedMode)
SWSetSpriteDrawProc(gSimpleSpriteP, BP8BitInterlacedMaskDrawProc);
else
SWSetSpriteDrawProc(gSimpleSpriteP, BlitPixie8BitMaskDrawProc);
}
else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) ) // Not 256 colors
{
// Use interlaced drawProcs unless in B&W, where interlacing is ugly
if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
SWSetSpriteDrawProc(gSimpleSpriteP, BPAllBitInterlacedMaskDrawProc);
else
SWSetSpriteDrawProc(gSimpleSpriteP, BlitPixieAllBitMaskDrawProc);
}
}
///--------------------------------------------------------------------------------------
// SetUpAnimation
///--------------------------------------------------------------------------------------
void SetUpAnimation( void )
{
Rect moveBoundsRect;
SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
ResetKeys();
// Set up data used by the SmoothScrollingWorldMoveProc
gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
CenterRect( &gScreenMidRect, &gSpriteWorldP->backRect );
SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
// movement boundary = size of tileMap
SetRect(&moveBoundsRect, 0, 0,
gTileMapStructP->numCols * kTileWidth,
gTileMapStructP->numRows * kTileHeight);
SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
// Move visScrollRect to starting sprite position
SWMoveVisScrollRect(gSpriteWorldP,
gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
if (gSpriteWorldP->pixelDepth == 8) // If in 256 colors
{
if (kInterlacedMode)
{
SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BP8BitInterlacedRectDrawProc);
SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BP8BitInterlacedRectDrawProc);
SWSetTileMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
SWSetDoubleRectDrawProc(gSpriteWorldP, BP8BitInterlacedDoubleRectDrawProc);
}
else
{
SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixie8BitRectDrawProc);
SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie8BitDoubleRectDrawProc);
}
} // When running on PPC, we can't use the AllBit blitters in lower than 8-bit
else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) ) // Not 256 colors
{
if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
{
// Use interlaced drawProcs unless in B&W, where interlacing is ugly
SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BPAllBitInterlacedRectDrawProc);
SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BPAllBitInterlacedRectDrawProc);
SWSetTileMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
if (gSpriteWorldP->pixelDepth == 16)
SWSetDoubleRectDrawProc(gSpriteWorldP, BP16BitInterlacedDoubleRectDrawProc);
}
else
{
SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
if (gSpriteWorldP->pixelDepth == 16)
SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie16BitDoubleRectDrawProc);
}
}
// Make sure CopyBits, if used, doesn't try to colorize things
SWSetPortToWindow(gSpriteWorldP);
ForeColor(blackColor);
BackColor(whiteColor);
SWDrawTilesInBackground(gSpriteWorldP);
SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
}
///--------------------------------------------------------------------------------------
// RunAnimation
///--------------------------------------------------------------------------------------
void RunAnimation( void )
{
unsigned long frames;
frames = 0;
StartTimer();
gEscapeKey = false;
while (!Button() && !gEscapeKey)
{
SWProcessScrollingSpriteWorld(gSpriteWorldP);
SWAnimateScrollingSpriteWorld(gSpriteWorldP);
// We call this in case the Control Strip or something changes our window's visRgn
KeepMenuBarHidden(gWindowP);
if (gSpriteWorldP->frameHasOccurred)
{
frames++;
if (gSpriteHitExit)
AdvanceLevel();
else if (gSpriteWasKilled)
KillSprite();
}
}
ShowMenuBar(gWindowP);
ShowResults(frames);
}
///--------------------------------------------------------------------------------------
// ShutDown (clean up and dispose of the SpriteWorld)
///--------------------------------------------------------------------------------------
void ShutDown( void )
{
SWDisposeSpriteWorld(gSpriteWorldP);
SWExitSpriteWorld();
FlushEvents(everyEvent, 0);
ShowCursor();
}
///--------------------------------------------------------------------------------------
// KeySpriteMoveProc
///--------------------------------------------------------------------------------------
SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
{
short horizDir, tempHorizDelta;
Boolean spriteIsOnGround = false;
UpdateKeys(); // Put the latest key values in the keys structure
// See if the sprite is standing on a wall
spriteIsOnGround = false;
if ( ((srcSpriteP->destFrameRect.bottom - gSpriteInsetRect.bottom) / kTileHeight) *
kTileHeight == srcSpriteP->destFrameRect.bottom - gSpriteInsetRect.bottom )
{
gSpriteInsetRect.bottom--; // Check one line lower than bottom of sprite
if (SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstWallTile, kLastWallTile, false) ||
SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstLeftFloorTile, kLastChangingTile, false) )
{
spriteIsOnGround = true;
}
gSpriteInsetRect.bottom++; // Change rect to the way it was before
}
horizDir = (gKeys.right - gKeys.left);
if (horizDir) // Are we moving left or right?
{
// Did we change direction?
if ( (srcSpriteP->horizMoveDelta > 0 && horizDir < 0) ||
(srcSpriteP->horizMoveDelta < 0 && horizDir > 0) )
{
srcSpriteP->horizMoveDelta = 0;
}
// Add speed to sprite
srcSpriteP->horizMoveDelta += horizDir * kWalkIncrease;
// Keep from moving too fast
if (srcSpriteP->horizMoveDelta > kMaxWalkSpeed)
srcSpriteP->horizMoveDelta = kMaxWalkSpeed;
else if (srcSpriteP->horizMoveDelta < -kMaxWalkSpeed)
srcSpriteP->horizMoveDelta = -kMaxWalkSpeed;
}
else // We're not moving, so slow down
{
if (srcSpriteP->horizMoveDelta > 0)
srcSpriteP->horizMoveDelta /= 2;
else if (srcSpriteP->horizMoveDelta < 0)
srcSpriteP->horizMoveDelta /= 2;
}
if (gKeys.up && gSpriteIsJumping) // Already jumping - continue going up
{
if (gSpriteJumpStage++ < kMaxSpriteJumpDistance)
{
srcSpriteP->vertMoveDelta = -kJumpSpeed + gSpriteJumpStage * 1.4;
}
else
{
gSpriteIsJumping = false;
}
}
else if (gKeys.up && gSpriteCanJump) // Start new jump
{
if (spriteIsOnGround)
{
srcSpriteP->vertMoveDelta = -kJumpSpeed;
gSpriteIsJumping = true;
gSpriteCanJump = false;
gSpriteJumpStage = 0;
}
}
else // Stopped jumping, so make it fall early
{
if (srcSpriteP->vertMoveDelta < 0)
srcSpriteP->vertMoveDelta += 3;
gSpriteIsJumping = false;
if (!gKeys.up && srcSpriteP->vertMoveDelta >= 0)
gSpriteCanJump = true;
}
// Add gravity
srcSpriteP->vertMoveDelta += kGravitySpeed;
// Keep ball from falling too fast
if (srcSpriteP->vertMoveDelta > kMaxFallSpeed)
srcSpriteP->vertMoveDelta = kMaxFallSpeed;
srcSpriteP->destFrameRect.top += srcSpriteP->vertMoveDelta;
srcSpriteP->destFrameRect.bottom += srcSpriteP->vertMoveDelta;
tempHorizDelta = 0;
// Check for collisions with walls vertically
if (srcSpriteP->vertMoveDelta > 0) // Moving down
{
// Make sure sprite was above the tile before we fell through it. Otherwise,
// the sprite was never on top, and shouldn't be moved by the platform.
if ( ((srcSpriteP->oldFrameRect.bottom-1) / kTileHeight) <
((srcSpriteP->destFrameRect.bottom-1) / kTileHeight) )
{
// Check for floors moving left
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstLeftFloorTile, kFirstLeftFloorTile, false) )
{
tempHorizDelta -= kMovingFloorForce;
}
// Check for floors moving right
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstRightFloorTile, kFirstRightFloorTile, false) )
{
tempHorizDelta += kMovingFloorForce;
}
}
// Make sure sprite was above the tile before we fell through it. If so, we
// move the sprite back on top of the tile, otherwise we never were on top.
if ( ((srcSpriteP->oldFrameRect.bottom-1 - kRunningCorrection) / kTileHeight) <
((srcSpriteP->destFrameRect.bottom-1) / kTileHeight) )
{
// Keep sprite from falling through moving floors
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstLeftFloorTile, kFirstRightFloorTile, true) )
{
srcSpriteP->vertMoveDelta = 0;
}
// Keep sprite from falling through a changing floor
else if ( gChangingFloorMode == true &&
SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstChangingTile, kFirstChangingTile, true) )
{
srcSpriteP->vertMoveDelta = 0;
}
}
// Make sure sprite doesn't fall through any walls
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWBottomSide,
&gSpriteInsetRect, kFirstWallTile, kLastWallTile, true) )
{
srcSpriteP->vertMoveDelta = 0;
}
}
else if (srcSpriteP->vertMoveDelta < 0) // Moving up
{
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWTopSide,
&gSpriteInsetRect, kFirstWallTile, kLastWallTile, true) )
{
srcSpriteP->vertMoveDelta /= 2;
gSpriteIsJumping = false;
}
}
srcSpriteP->destFrameRect.right += srcSpriteP->horizMoveDelta + tempHorizDelta;
srcSpriteP->destFrameRect.left += srcSpriteP->horizMoveDelta + tempHorizDelta;
gSpriteInsetRect.bottom += kRunningCorrection;
// Check for collisions with walls horizontally
if (srcSpriteP->horizMoveDelta + tempHorizDelta > 0) // Moving right
{
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWRightSide,
&gSpriteInsetRect, kFirstWallTile, kLastWallTile, true) )
{
if (srcSpriteP->horizMoveDelta > 0)
srcSpriteP->horizMoveDelta = 1;
}
}
else if (srcSpriteP->horizMoveDelta + tempHorizDelta < 0) // Moving left
{
if ( SWCheckSpriteWithTiles(gSpriteWorldP, srcSpriteP, kSWLeftSide,
&gSpriteInsetRect, kFirstWallTile, kLastWallTile, true) )
{
if (srcSpriteP->horizMoveDelta < 0)
srcSpriteP->horizMoveDelta = -1;
}
}
gSpriteInsetRect.bottom -= kRunningCorrection;
srcSpriteP->needsToBeDrawn = true;
// See if sprite hit exit sign or spikes
if (SWCheckSpriteWithTiles(gSpriteWorldP, gSimpleSpriteP, kSWEntireSprite,
&gSpriteInsetRect, kFirstExitTile, kLastExitTile, false) )
{
gSpriteHitExit = true;
}
else if (gSpikesAreUp && SWCheckSpriteWithTiles(gSpriteWorldP, gSimpleSpriteP,
kSWEntireSprite, &gSpriteInsetRect, kFirstSpikeTile, kLastSpikeTile, false) )
{
gSpriteWasKilled = true;
}
}
///--------------------------------------------------------------------------------------
// TileChangeProc
///--------------------------------------------------------------------------------------
SW_FUNC void TileChangeProc(SpriteWorldPtr spriteWorldP)
{
short curImage;
static short wallDelay = 0, spikeTimer = 0, spikeDirection = 0, spikeDelay = 0;
static short changingFloorDelay = 0, changingFloorWait = 0, exitDelay = 0;
static Boolean spikesAreMoving = false;
static short oldTicks = 0;
short ticksPassed, ticks;
// Initialize oldTicks the first time this function is called
if (oldTicks == 0)
oldTicks = TickCount();
ticks = TickCount();
ticksPassed = ticks - oldTicks; // Number of ticks passed since last call
oldTicks = ticks;
changingFloorWait += ticksPassed;
if (changingFloorWait >= kChangingFloorWait)
{
changingFloorWait = 0;
if (gChangingFloorMode == true)
{
gChangingFloorMode = 0;
SWChangeTileImage(spriteWorldP, kFirstChangingTile, kBackgroundTile);
}
else
{
gChangingFloorMode = 1;
SWChangeTileImage(spriteWorldP, kFirstChangingTile, kFirstChangingTile);
}
}
// Change the changing floor
if (gChangingFloorMode == true)
{
changingFloorDelay += ticksPassed;
if (changingFloorDelay >= kChangingFloorSpeed)
{
curImage = spriteWorldP->curTileImage[kFirstChangingTile];
if (curImage < kLastChangingTile)
curImage++;
else
curImage = kFirstChangingTile;
SWChangeTileImage(spriteWorldP, kFirstChangingTile, curImage);
changingFloorDelay = 0;
}
}
// Change the moving floors
wallDelay += ticksPassed;
if (wallDelay >= kMovingFloorSpeed)
{
// Move the left wall
curImage = spriteWorldP->curTileImage[kFirstLeftFloorTile];
if (curImage < kLastLeftFloorTile)
curImage++;
else
curImage = kFirstLeftFloorTile;
SWChangeTileImage(spriteWorldP, kFirstLeftFloorTile, curImage);
// Move the right wall
curImage = spriteWorldP->curTileImage[kFirstRightFloorTile];
if (curImage < kLastRightFloorTile)
curImage++;
else
curImage = kFirstRightFloorTile;
SWChangeTileImage(spriteWorldP, kFirstRightFloorTile, curImage);
wallDelay = 0;
}
// Change the spikes
if (spikesAreMoving)
{
spikeDelay += ticksPassed;
if (spikeDelay >= kSpikeSpeed)
{
curImage = spriteWorldP->curTileImage[kFirstSpikeTile];
curImage += spikeDirection;
if (curImage == kLastSpikeTile+1 || curImage == kFirstSpikeTile)
{
spikesAreMoving = false;
if (spikeDirection > 0)
spikeDirection = -1;
else
spikeDirection = 1;
}
// Determine whether the current spike position can kill the sprite
if (curImage > kFirstSpikeTile + 7)
gSpikesAreUp = false;
else
gSpikesAreUp = true;
SWChangeTileImage(spriteWorldP, kFirstSpikeTile, curImage);
spikeDelay = 0;
}
}
else
{
spikeTimer += ticksPassed;
if (spikeTimer > kSpikeChangeDelay)
{
spikeTimer = 0;
spikesAreMoving = true;
}
}
// Animate the exit sign
exitDelay += ticksPassed;
if (exitDelay >= kExitSignSpeed)
{
curImage = spriteWorldP->curTileImage[kFirstExitTile];
if (curImage < kLastExitTile)
curImage++;
else
curImage = kFirstExitTile;
SWChangeTileImage(spriteWorldP, kFirstExitTile, curImage);
exitDelay = 0;
}
}
///--------------------------------------------------------------------------------------
// SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
///--------------------------------------------------------------------------------------
SW_FUNC void SmoothScrollingWorldMoveProc(
SpriteWorldPtr spriteWorldP,
SpritePtr followSpriteP)
{
short screenMidRectTop, screenMidRectLeft;
screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
spriteWorldP->horizScrollDelta = (kMaxWalkSpeed *
(followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
spriteWorldP->vertScrollDelta = (kMaxFallSpeed *
(followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
if (kInterlacedMode)
spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
}
///--------------------------------------------------------------------------------------
// UpdateKeys (Put the latest key values in the keys structure)
///--------------------------------------------------------------------------------------
void UpdateKeys( void )
{
EventRecord event;
short theKey;
Boolean isDown;
while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
{
theKey = (event.message & keyCodeMask) >> 8;
isDown = (event.what != keyUp);
if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
gKeys.left = isDown;
else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
gKeys.right = isDown;
else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
gKeys.down = isDown;
else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
gKeys.up = isDown;
else if (theKey == kEscKey)
gEscapeKey = isDown;
}
}
///--------------------------------------------------------------------------------------
// ResetKeys (Called when setting up a new game)
///--------------------------------------------------------------------------------------
void ResetKeys( void )
{
gKeys.left = 0;
gKeys.right = 0;
gKeys.down = 0;
gKeys.up = 0;
gEscapeKey = 0;
}
///--------------------------------------------------------------------------------------
// AdvanceLevel
///--------------------------------------------------------------------------------------
void AdvanceLevel( void )
{
Rect moveBoundsRect;
unsigned long junkTime;
OSErr err;
gCurrentLevel++;
gSpriteHitExit = false;
SWDisposeTileMap(&gTileMapStructP);
err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
if (err)
{
gCurrentLevel = 128;
err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
FatalError(err);
}
gTileMap = gTileMapStructP->tileMap;
SWInstallTileMap(gSpriteWorldP, gTileMapStructP);
// Reset scrolling moveBounds for new TileMap
SetRect(&moveBoundsRect, 0, 0,
gTileMapStructP->numCols * kTileWidth,
gTileMapStructP->numRows * kTileHeight);
SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
ResetSprite();
Delay(30, &junkTime);
SWDrawTilesInBackground(gSpriteWorldP);
SWUpdateSpriteWorld(gSpriteWorldP, false);
}
///--------------------------------------------------------------------------------------
// KillSprite
///--------------------------------------------------------------------------------------
void KillSprite( void )
{
unsigned long dummyTicks;
gSpriteWasKilled = false;
SWSetSpriteFrameTime(gSimpleSpriteP, 1000/15);
SWSetSpriteFrameAdvance(gSimpleSpriteP, 1);
SWSetSpriteMoveProc(gSimpleSpriteP, NULL);
do
{ // Run the "popped ball" animation
SWProcessScrollingSpriteWorld(gSpriteWorldP);
SWAnimateScrollingSpriteWorld(gSpriteWorldP);
} while (gSimpleSpriteP->curFrameIndex < gSimpleSpriteP->maxFrames-1);
Delay(23, &dummyTicks);
ResetSprite();
}
///--------------------------------------------------------------------------------------
// ResetSprite
///--------------------------------------------------------------------------------------
void ResetSprite( void )
{
SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
SWMoveSprite(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
SWMoveVisScrollRect(gSpriteWorldP, 0, 0);
SWSetSpriteFrameAdvance(gSimpleSpriteP, 0);
SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
SWSetCurrentFrameIndex(gSimpleSpriteP, 0);
gSpriteCanJump = false;
gSpriteIsJumping = false;
gSpriteJumpStage = 0;
}